﻿#pragma once

#include "../../thirdparty/http_parser/http_parser.h"
#include "../argument/box_argument.hh"
#include "../http/http_base.hh"
#include "../http/http_call.hh"
#include "../util/object_pool.hh"
#include <cstdint>
#include <functional>
#include <memory>
#include <string>
#include <unordered_map>

struct http_parser_settings;
struct http_parser;

namespace kratos {
namespace http {

class HttpBaseImpl;
using HeaderMap = std::unordered_map<std::string, std::string>;

/**
 * HTTP调用接口实现类
 */
class HttpCallImpl : public HttpCall {
  std::uint64_t channel_id_{0}; ///< 调用关联的管道ID
  std::string host_;            ///< 调用的远程主机地址或域名
  int port_{80};                ///< 调用的远程主机的端口
  HttpBaseImpl *base_{nullptr}; ///< HTTP框架实现类
  kratos::unique_pool_ptr<char> buffer_; ///< HTTP数据缓冲区
  std::size_t buffer_length_{0};         ///< 缓冲区内数据长度，字节
  std::size_t max_buffer_length_{1024 *
                                 64}; ///< 缓冲区最大长度，缓冲区会自动增长
  HeaderMap header_map_;              ///< HTTP头
  std::string last_header_key_; ///< 用于HTTP解析解析
  std::size_t body_start_{0};   ///< HTTP消息体在缓冲区内的起始位置
  std::size_t body_length_{0};  ///< HTTP消息体在缓冲区内结束位置
  std::string body_;            ///< HTTP消息体
  std::string uri_{"/"};        ///< URI
  int status_code_{200};        ///< HTTP状态码
  std::string method_;          ///< HTTP请求类型
  std::uint64_t coro_id_{0};    ///< 协程ID
  bool msg_complete_{false}; ///< 消息是否接收完成并已经解析完毕
  std::uint64_t user_data_{0}; ///< 用户数据

protected:
  kratos::unique_pool_ptr<http_parser> parser_; ///< HTTP协议解析器
  kratos::unique_pool_ptr<http_parser_settings>
      settings_; ///< HTTP解析器回调函数配置

public:
  HttpCallImpl();
  virtual ~HttpCallImpl();
  virtual auto set_host(const std::string &host) -> void override;
  virtual auto get_host() -> const std::string & override;
  virtual auto set_port(int port) -> void override;
  virtual auto get_port() -> int override;
  virtual auto get_headers() -> const HeaderMap & override;
  auto set_headers(const HeaderMap &headers) -> void override;
  virtual auto add_header(const std::string &key, const std::string &value)
      -> void override;
  virtual auto get_content() -> std::string override;
  virtual auto set_content(const std::string &content) -> void override;
  virtual auto get_full_content() -> std::string override;
  virtual auto get_method() -> const std::string & override;
  virtual auto set_method(const std::string &method) -> void override;
  virtual auto set_status_code(int code) -> void override;
  virtual auto get_status_code() -> int override;
  virtual auto get_uri() -> std::string override;
  virtual auto set_uri(const std::string &url) -> void override;
  virtual auto get_response() -> HttpCallPtr override;

public:
  /**
   * 发送HTTP请求.
   *
   * \return
   */
  virtual auto send_request() -> void;
  /**
   * 发送HTTP响应.
   *
   * \return
   */
  virtual auto send_response() -> void;
  /**
   * 完成HTTP协议解析.
   *
   * \return
   */
  virtual auto finish_parse() -> void;
  /**
   * 设置HTTP框架接口实现.
   *
   * \param base
   * \return
   */
  auto set_base(HttpBaseImpl *base) -> void;
  /**
   * 获取HTTP框架接口实现.
   *
   * \return
   */
  auto get_base() -> HttpBaseImpl *;
  /**
   * 设置HTTP通信的管道ID.
   *
   * \param channel_id 管道ID
   * \return
   */
  auto set_channel_id(std::uint64_t channel_id) -> void;
  /**
   * 获取HTTP通信的管道ID.
   *
   * \return 管道ID
   */
  auto get_channel_id() -> std::uint64_t;
  /**
   * 是否开启了Keep-Alive.
   *
   * \return true或false
   */
  auto is_keep_alive() -> bool;
  /**
   * 获取HTTP协议解析器.
   *
   * \return HTTP协议解析器
   */
  auto get_parser() -> http_parser *;
  /**
   * 获取HTTP协议解析回调配置.
   *
   * \return HTTP协议解析回调配置
   */
  auto get_settings() -> http_parser_settings *;
  /**
   * 获取HTTP协议缓冲区指针.
   *
   * \return HTTP协议缓冲区指针
   */
  auto get_buffer() -> const char *;
  /**
   * 根据接收到字节长度动态扩容.
   *
   * \param recved_bytes 收到字节长度
   * \return 扩容后的缓冲区指针
   */
  auto get_resized_buffer(std::size_t recved_bytes) -> char *;
  /**
   * 调整接收到的字节长度.
   *
   * \param recved_bytes 收到的字节长度
   * \return
   */
  auto adjust_buffer_length(std::size_t recved_bytes) -> void;
  /**
   * 获取缓冲区内已接收到的字节长度.
   *
   * \return 缓冲区内已接收到的字节长度
   */
  auto get_buffer_len() -> std::size_t;
  /**
   * 设置协议体在协议缓冲区的起始地址和协议体字节长度.
   *
   * \param body_at 协议缓冲区的起始地址
   * \param body_len 协议体字节长度
   * \return
   */
  auto set_body_info(const char *body_at, std::size_t body_len) -> void;
  /**
   * 设置当前协议头的键.
   *
   * \param key 协议头的键
   * \return
   */
  auto add_header_key(const std::string &key) -> void;
  /**
   * 设置当前协议头的值.
   *
   * \param value 协议头的值
   * \return
   */
  auto add_header_value(const std::string &value) -> void;
  /**
   * 关闭HTTP管道并触发资源清理.
   *
   * \return
   */
  auto close() -> void;
  /**
   * 记录协程ID并出让CPU.
   *
   * \return
   */
  auto run_coro() -> void;
  /**
   * 唤醒运行本次HTTP调用的协程.
   *
   * \return
   */
  auto wakeup() -> void;
  /**
   * 检测是否在协程内运行.
   *
   * \return true或false
   */
  auto is_coro() -> bool;
  /**
   * 设置完成标志.
   *
   * \return
   */
  auto set_msg_complete() -> void;
  /**
   * 检测是否消息完成.
   *
   * \return true或false
   */
  auto is_msg_complete() -> bool;
  /**
   * @brief 设置用户数据
   * @param user_data 用户数据
   * @return 
  */
  auto set_user_data(std::uint64_t user_data) ->void;
  /**
   * @brief 获取用户数据
   * @return 用户数据
  */
  auto get_user_data() -> std::uint64_t;
};

/**
 * HTTP请求调用.
 */
class HttpRequest : public HttpCallImpl {
  ResponseHandler handler_; ///< HTTP响应处理器

public:
  /**
   * 构造.
   *
   */
  HttpRequest();
  /**
   * 析构.
   *
   */
  virtual ~HttpRequest() {}
  /**
   * 设置处理器.
   *
   * \param handler 处理器
   * \return
   */
  auto set_handler(ResponseHandler handler) -> void;
  /**
   * 获取处理器.
   *
   * \return 处理器
   */
  auto get_handler() -> ResponseHandler;
  /**
   * 处理完成，销毁资源.
   *
   * \return
   */
  virtual auto finish() -> void override;
};

/**
 * HTTP响应调用.
 */
class HttpResponse : public HttpCallImpl {
  RequestHandler handler_;                      ///< HTTP请求处理器
  std::shared_ptr<HttpResponse> user_response_; ///< 需要返回的响应

public:
  /**
   * 构造.
   *
   */
  HttpResponse();
  /**
   * 析构.
   *
   */
  virtual ~HttpResponse() {}
  /**
   * 设置处理器.
   *
   * \param handler 处理器
   * \return
   */
  auto set_handler(RequestHandler handler) -> void;
  /**
   * 获取处理器.
   *
   * \return 处理器
   */
  auto get_handler() -> RequestHandler;
  /**
   * 处理完成，销毁资源.
   *
   * \return
   */
  virtual auto finish() -> void override;
  /**
   * 获取响应.
   *
   * \return 响应
   */
  virtual auto get_response() -> HttpCallPtr override;
};

} // namespace http
} // namespace kratos
